package com.baozhun.mall.common.util

import android.content.Context
import android.text.TextUtils
import cn.jpush.android.api.JPushInterface
import com.baozhun.mall.common.base.BaseApplication
import com.baozhun.mall.common.model.bean.AppConfigBean
import com.baozhun.mall.common.model.bean.RegionBean
import com.baozhun.mall.common.model.bean.UserInfo
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import com.orhanobut.logger.Logger
import com.tencent.mmkv.MMKV
import java.io.File
import java.text.DecimalFormat
import kotlin.math.log10
import kotlin.math.pow

/**
 * @Title：本地缓存类，通过mmkv实现
 * @Description：
 * @Author：xuefeng.zhu
 * @Since：2022/11/4
 * @Version：1.0.0
 */
object CacheUtil {
    private const val MAP_ID = "roots"
    private const val KEY_USER = "user"
    private const val APP_CONFIG_INFO = "appConfigBean"
    private const val KEY_IS_LOGIN = "is_login"
    private const val KEY_FIRST_LONGIN = "first_login"
    private const val KEY_AGREE_PRIVACY_STATUS = "privacy_protocol_status"
    private const val KEY_SEARCH_HISTORY = "search_history"
    private const val KEY_CITY_LIST = "city_list"
    private const val KEY_REGION_LIST = "region_list"


    fun getRegionListCache(): MutableList<RegionBean> {
        val kv = MMKV.mmkvWithID(MAP_ID)
        val dataString = kv.decodeString(KEY_REGION_LIST)
        return if (TextUtils.isEmpty(dataString)) {
            mutableListOf()
        } else {
            val listType = object : TypeToken<MutableList<RegionBean>>() {}.type
            Gson().fromJson(dataString, listType)
        }
    }

    fun saveRegionList(data: MutableList<RegionBean>) {
        val kv = MMKV.mmkvWithID(MAP_ID)
        if (data.isNotEmpty()) {
            kv.encode(KEY_REGION_LIST, Gson().toJson(data))
        }
    }

    /**
     * 设置配置信息
     */
    fun setAppConfig(appConfigBean: AppConfigBean) {
        val kv = MMKV.mmkvWithID(MAP_ID)
        kv.encode(APP_CONFIG_INFO, Gson().toJson(appConfigBean))
    }

    /**
     * 获取配置信息
     */
    fun getAppConfig(): AppConfigBean {
        val kv = MMKV.mmkvWithID(MAP_ID)
        val appConfigInfo = kv.decodeString(APP_CONFIG_INFO)
        return if (TextUtils.isEmpty(appConfigInfo)) {
            AppConfigBean()
        } else {
            Gson().fromJson(appConfigInfo, AppConfigBean::class.java)
        }
    }

    /**
     * 获取搜索历史
     */
    fun getSearchHistory(): MutableList<String> {
        val kv = MMKV.mmkvWithID(MAP_ID)
        val historyString = kv.decodeString(KEY_SEARCH_HISTORY)
        return if (TextUtils.isEmpty(historyString)) {
            mutableListOf()
        } else {
            val listType = object : TypeToken<MutableList<String>>() {}.type
            Gson().fromJson(historyString, listType)
        }
    }

    /**
     * 缓存搜索历史
     */
    fun setSearchHistory(history: List<String>) {
        val kv = MMKV.mmkvWithID(MAP_ID)
        if (history.isEmpty()) {
            kv.encode(KEY_SEARCH_HISTORY, "")
        } else {
            kv.encode(KEY_SEARCH_HISTORY, Gson().toJson(history))
        }
    }

    /**
     * 获取保存的账户信息
     */
    fun getUser(): UserInfo {
        val kv = MMKV.mmkvWithID(MAP_ID)
        val userStr = kv.decodeString(KEY_USER)
        return if (TextUtils.isEmpty(userStr)) {
            UserInfo()
        } else {
            Gson().fromJson(userStr, UserInfo::class.java)
        }
    }

    /**
     * 设置账户信息
     */
    fun setUser(userResponse: UserInfo?, useOldToken: Boolean = true, setAlias: Boolean = false) {
        val kv = MMKV.mmkvWithID(MAP_ID)
        if (userResponse == null) {
            kv.encode(KEY_USER, "")
            setIsLogin(false)
        } else {
            var accessToken = getUser().token
            if (accessToken.isNotEmpty() && useOldToken) userResponse.token = accessToken
            kv.encode(KEY_USER, Gson().toJson(userResponse))
            setIsLogin(true)
        }
        userResponse?.id?.let {
            if (it.isNotEmpty() && setAlias) {
                Logger.e("JPushInterface Alias==>$it")
                JPushInterface.setAlias(BaseApplication.mInstance, 1, it)
            }
        }
    }

    /**
     * 清除用户信息
     */
    fun clearUserInfo() {
        //清除极光alias
        JPushInterface.deleteAlias(BaseApplication.mInstance, 1)
        //清空用户信息
        setUser(null)
    }

    /**
     * 是否已经登录
     */
    fun isLogin(): Boolean {
        val kv = MMKV.mmkvWithID(MAP_ID)
        return kv.decodeBool(KEY_IS_LOGIN, false)
    }

    /**
     * 是否未登录
     */
    fun isNotLogin(): Boolean {
        return !isLogin()
    }

    /**
     * 设置是否已经登录
     */
    private fun setIsLogin(isLogin: Boolean) {
        val kv = MMKV.mmkvWithID(MAP_ID)
        kv.encode(KEY_IS_LOGIN, isLogin)
    }

    /**
     * 是否是第一次登陆
     */
    fun isFirstOpen(): Boolean {
        val kv = MMKV.mmkvWithID(MAP_ID)
        return kv.decodeBool(KEY_FIRST_LONGIN, true)
    }


    /**
     * 是否是第一次登陆
     */
    fun setFirst(first: Boolean): Boolean {
        val kv = MMKV.mmkvWithID(MAP_ID)
        return kv.encode(KEY_FIRST_LONGIN, first)
    }


    /**
     * 设置营私协议状态
     */
    fun setPrivacyProtocolStatus(agree: Boolean) {
        val kv = MMKV.mmkvWithID(MAP_ID)
        kv.encode(KEY_AGREE_PRIVACY_STATUS, agree)
    }

    /**
     * 是否同意营私协议
     */
    fun isAgreePrivacyProtocol(): Boolean {
        val kv = MMKV.mmkvWithID(MAP_ID)
        return kv.decodeBool(KEY_AGREE_PRIVACY_STATUS, false)
    }

    /**
     * 获取glide的缓存大小
     */
    fun getGlideCacheSize(context: Context): String? {
        return try {
            var size: Long = 0
            //        size += getDirSize(context.cacheDir)
            //只获取glide缓存大小
            size += getDirSize(File("${context.cacheDir}/image_manager_disk_cache"))
            //        context.externalCacheDir?.let { size += getDirSize(it) }
            readableFileSize(size)
        } catch (e: Exception) {
            e.printStackTrace()
            "0M"
        }
    }

    /**
     * 获取对应文件夹缓存大小
     */
    private fun getDirSize(dir: File): Long {
        var size: Long = 0
        for (file in dir.listFiles()) {
            if (file != null && file.isDirectory) {
                size += getDirSize(file)
            } else if (file != null && file.isFile) {
                size += file.length()
            }
        }
        return size
    }

    /**
     * 格式化文件大小
     */
    private fun readableFileSize(size: Long): String? {
        if (size <= 0) return "0 B"
        val units = arrayOf("B", "KB", "MB", "GB", "TB")
        val digitGroups = (log10(size.toDouble()) / log10(1024.0)).toInt()
        return DecimalFormat("#,##0.#").format(size / 1024.0.pow(digitGroups.toDouble())) + " " + units[digitGroups]
    }
}